package com.austin.framework.cacheableExtend;

import com.austin.framework.cacheableExtend.model.CacheInvocation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 自定义CustomRedisCacheManager，扩展RedisCacheManager
 *
 * @author: austin
 * @since: 2023/2/18 18:15
 */
public class CustomRedisCacheManager extends RedisCacheManager implements BeanFactoryAware {

    private Map<String, RedisCacheConfiguration> initialCacheConfigurations;

    private RedisTemplate cacheRedisTemplate;

    private RedisCacheWriter cacheWriter;

    private DefaultListableBeanFactory beanFactory;

    /**
     * 缓存配置信息
     */
    private RedisCacheConfiguration defaultCacheConfiguration;

    /**
     * 标记了缓存注解的方法类信息,用于主动刷新缓存时调用原始方法加载数据
     */
    protected CacheInvocation CacheInvocation;

    /**
     * 封装一个自定义缓存管理器
     *
     * @param cacheWriter
     * @param defaultCacheConfiguration
     * @param initialCacheConfigurations
     * @param cacheRedisTemplate
     */
    public CustomRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration,
                                   Map<String, RedisCacheConfiguration> initialCacheConfigurations, RedisTemplate cacheRedisTemplate) {
        super(cacheWriter, defaultCacheConfiguration, initialCacheConfigurations);
        this.initialCacheConfigurations = initialCacheConfigurations;
        this.cacheRedisTemplate = cacheRedisTemplate;
        this.cacheWriter = cacheWriter;
        this.defaultCacheConfiguration = defaultCacheConfiguration;
        //采用spring事件驱动亦可
        //EventBusHelper.register(this);
    }

    public CustomRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }

    public Map<String, RedisCacheConfiguration> getInitialCacheConfigurations() {
        return initialCacheConfigurations;
    }

    @Override
    protected Collection<RedisCache> loadCaches() {
        List<RedisCache> caches = new LinkedList<>();
        /**
         * Map<String, RedisCacheConfiguration> getInitialCacheConfigurations()这里的值为CacheExpireTimeInit.afterSingletonInstanced()方法
         *
         * 根据注解初始化的缓存
         */
        for (Map.Entry<String, RedisCacheConfiguration> entry : getInitialCacheConfigurations().entrySet()) {
            caches.add(createRedisCache(entry.getKey(), entry.getValue()));
        }
        return caches;
    }

    @Override
    public RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
        CustomRedisCache CustomRedisCache = new CustomRedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfiguration);
        return CustomRedisCache;
    }


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }


    public RedisTemplate getCacheRedisTemplate() {
        return cacheRedisTemplate;
    }

    public CacheInvocation getCacheInvocation() {
        return CacheInvocation;
    }

    /**
     * 自定义缓存管理器，接收CacheInvocation
     *
     * @param CacheInvocation
     */
    @EventListener
    private void doWithCacheInvocationEvent(CacheInvocation CacheInvocation) {
        this.CacheInvocation = CacheInvocation;
    }
}
